/**
 * 小说章节解析器
 */

// 常见章节正则表达式
const CHAPTER_PATTERNS = [
  // 第X章 章节名
  /^第[0-9零一二三四五六七八九十百千万]+章\s*.{0,30}/gm,
  // 第X节 节名
  /^第[0-9零一二三四五六七八九十百千万]+节\s*.{0,30}/gm,
  // 第X卷 卷名
  /^第[0-9零一二三四五六七八九十百千万]+卷\s*.{0,30}/gm,
  // 第X回 回名
  /^第[0-9零一二三四五六七八九十百千万]+回\s*.{0,30}/gm,
  // 数字章节 1. 章节名
  /^\d+\.\s*.{0,30}/gm,
  // 数字章节 1、章节名
  /^\d+、\s*.{0,30}/gm,
  // 居中的章节标题（大量空格+第X章）
  /^\s{5,}第[0-9零一二三四五六七八九十百千万]+章.{0,30}/gm,
  // 居中的章节号+章节名
  /^\s{5,}第.{1,10}章.{0,30}/gm,
  // 居中的小节编号（一）等
  /^\s{5,}[（(][一二三四五六七八九十]{1,3}[)）]/gm,
  // 普通章节名（章节名通常较短）
  /^第.{1,10}章.{0,30}/gm,
];

// 特殊章节关键词（用于辅助识别）
const CHAPTER_KEYWORDS = [
  '序言', '序章', '楔子', '尾声', '后记', '番外', '终章', '完结', '结局', '引子'
];

/**
 * 解析文本内容中的章节
 * @param {string} content 小说内容
 * @param {string} novelId 小说ID
 * @returns {Array} 章节数组
 */
export function parseChapters(content, novelId) {
  // 预处理内容，规范化换行符
  content = content.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
  
  const chapters = [];
  let chapterId = 0;
  
  // 改进1: 使用分段处理策略，避免一次性匹配整个内容
  const contentLines = content.split('\n');
  let allMatches = [];

  // 改进2: 通过线性扫描代替大量正则匹配
  // 先生成所有可能匹配的行号和位置
  const possibleChapters = [];
  let currentPosition = 0;
  
  for (let i = 0; i < contentLines.length; i++) {
    const line = contentLines[i];
    const lineLength = line.length + 1; // +1 是为了包含换行符
    
    // 如果是短行（可能是章节标题）且不是空行
    if (line.trim().length > 0 && line.trim().length < 50) {
      // 快速检查是否包含关键词
      const containsChapterKeyword = 
        line.includes('章') || 
        line.includes('节') || 
        line.includes('卷') || 
        line.includes('回') || 
        CHAPTER_KEYWORDS.some(keyword => line.includes(keyword));
      
      if (containsChapterKeyword) {
        possibleChapters.push({
          line,
          position: currentPosition,
          lineIndex: i
        });
      }
    }
    
    currentPosition += lineLength;
  }
  
  // 改进3: 只对可能的章节行应用正则表达式，不匹配整个文本
  if (possibleChapters.length > 0) {
    for (const possible of possibleChapters) {
      // 尝试用每个模式匹配
      let isMatch = false;
      
      // 检查是否匹配任一模式
      for (const pattern of CHAPTER_PATTERNS) {
        if (pattern.test(possible.line)) {
          isMatch = true;
          break;
        }
      }
      
      // 检查是否完全匹配关键字
      if (!isMatch) {
        const trimmedLine = possible.line.trim();
        if (CHAPTER_KEYWORDS.includes(trimmedLine)) {
          isMatch = true;
        }
      }
      
      if (isMatch) {
        allMatches.push({
          index: possible.position,
          [0]: possible.line,
          line: possible.line
        });
      }
    }
  }
  
  // 如果找到了足够多的章节，则进行排序和处理
  if (allMatches.length > 0) {
    // 按照在文本中出现的位置排序
    allMatches.sort((a, b) => a.index - b.index);
    
    // 移除太靠近的匹配（可能是重复检测到的章节）
    const MIN_CHAPTER_LENGTH = 200; // 章节最小长度，过滤噪声
    const filteredMatches = [];
    
    for (let i = 0; i < allMatches.length; i++) {
      const match = allMatches[i];
      if (i === 0) {
        filteredMatches.push(match);
      } else {
        const prevMatch = filteredMatches[filteredMatches.length - 1];
        // 如果两个章节开始位置相距太近，则认为是同一章节的不同部分
        if (match.index - prevMatch.index >= MIN_CHAPTER_LENGTH) {
          filteredMatches.push(match);
        }
      }
    }
    
    // 改进4: 批量构建章节数组，减少循环中的对象创建
    const chapterData = filteredMatches.map((match, index) => {
      const position = match.index;
      const title = match[0].trim();
      const endPosition = index < filteredMatches.length - 1 
        ? filteredMatches[index + 1].index 
        : content.length;
      
      return {
        position,
        title,
        endPosition,
        length: endPosition - position
      };
    });
    
    // 改进5: 一次性构建所有章节对象
    chapters.push(...chapterData.map(data => ({
      id: `${novelId}_${chapterId++}`,
      novelId,
      title: data.title,
      position: data.position,
      endPosition: data.endPosition,
      length: data.length
    })));
  }
  
  // 如果找不到合适的章节，尝试按固定长度切分
  if (chapters.length === 0) {
    console.log('未能识别章节，使用固定长度切分');
    const MAX_CHAPTER_SIZE = 10000; // 约10KB一章
    let position = 0;
    
    // 改进6: 减少循环中的对象创建
    const defaultChapters = [];
    
    while (position < content.length) {
      const endPosition = Math.min(position + MAX_CHAPTER_SIZE, content.length);
      // 尝试在段落边界切分
      let adjustedEnd = endPosition;
      if (endPosition < content.length) {
        // 向后找最近的段落结束
        const nextNewline = content.indexOf('\n', endPosition);
        if (nextNewline !== -1 && nextNewline - endPosition < 500) { // 不要找太远
          adjustedEnd = nextNewline + 1;
        }
      }
      
      defaultChapters.push({
        position,
        endPosition: adjustedEnd,
        length: adjustedEnd - position,
      });
      
      position = adjustedEnd;
    }
    
    chapters.push(...defaultChapters.map((data, index) => ({
      id: `${novelId}_${index}`,
      novelId,
      title: `第${index + 1}部分`,
      position: data.position,
      endPosition: data.endPosition,
      length: data.length
    })));
  }
  
  // 如果还是没有章节，创建一个默认章节
  if (chapters.length === 0) {
    chapters.push({
      id: `${novelId}_0`,
      novelId,
      title: '全文',
      position: 0,
      endPosition: content.length,
      length: content.length
    });
  }
  
  return chapters;
}

/**
 * 获取章节内容
 * @param {string} content 小说全文内容
 * @param {Object} chapter 章节信息
 * @returns {string} 章节内容
 */
export function getChapterContent(content, chapter) {
  return content.substring(chapter.position, chapter.endPosition);
}

/**
 * 检测文本编码
 * @param {string} text - 需要检测编码的文本
 * @returns {string} - 返回编码类型 'gbk' 或 'utf-8'
 */
export function detectEncoding(text) {
  if (!text) return 'utf-8';
  
  // 检查是否存在明显的乱码特征
  // 如果文本中有大量特殊字符，很可能是GBK编码被错误解析
  const specialCharsCount = (text.match(/[^\u0000-\u007F\u4e00-\u9fa5\u3000-\u303F\uFF00-\uFFEF]/g) || []).length;
  const specialCharRatio = specialCharsCount / text.length;
  
  // 如果超过20%的字符是非ASCII、非中文、非中文标点，可能是编码问题
  if (specialCharRatio > 0.2) {
    console.log('检测到大量特殊字符，疑似GBK编码问题', { specialCharRatio });
    return 'gbk';
  }
  
  // 检查问号比例
  const questionMarksCount = (text.match(/\?/g) || []).length;
  const questionMarkRatio = questionMarksCount / text.length;
  if (questionMarkRatio > 0.1) {
    console.log('检测到大量问号字符，疑似编码问题', { questionMarkRatio });
    return 'gbk';
  }
  
  // 检查直接匹配明显的乱码特征
  const obviousGarbledText = /С|Ů|ӣ|ǰ|ĸ|ʱ|˵|һ/.test(text.substring(0, 500));
  
  if (obviousGarbledText) {
    console.log('检测到明显的GBK乱码特征');
    return 'gbk';
  }
  
  // 检查常见的编码问题
  // 出现大量符号（Unicode替换字符U+FFFD）通常表示编码问题
  const problematicCharsRegex = /(\ufffd|\u65533){10,}/g;
  if (problematicCharsRegex.test(text)) {
    console.log('检测到大量Unicode替换字符');
    return 'gbk';
  }
  
  // 检查常见乱码模式
  const garbledPatterns = [
    /\{{3,}/,           // 连续3个以上花括号
    /(\?{3,}|\){3,}|\]{3,})/,  // 连续多个问号或括号
    /[^\x00-\xff]{5,}/,  // 连续5个以上非ASCII字符
  ];
  
  // 检查乱码模式数量
  let garbledCount = 0;
  garbledPatterns.forEach(pattern => {
    if (pattern.test(text)) garbledCount++;
  });
  
  if (garbledCount >= 1) {
    console.log('检测到乱码模式');
    return 'gbk';
  }
  
  return 'utf-8';
}

/**
 * 格式化章节内容，处理不同编码问题
 * @param {string} content - 章节内容
 * @param {string} encoding - 编码设置 (auto, utf-8, gbk)
 * @returns {string} - 格式化后的内容
 */
export function formatChapterContent(content, encoding = 'auto') {
  if (!content) return '';
  
  // 如果设置为自动，先检测编码
  let detectedEncoding = encoding;
  if (encoding === 'auto') {
    detectedEncoding = detectEncoding(content);
  }
  
  // 如果检测到GBK编码问题，尝试修复常见问题
  if (detectedEncoding === 'gbk') {
    // 尝试替换常见乱码序列
    let fixedContent = content;
    
    // 替换常见乱码序列 - 中文字符处理
    const chineseReplacements = [
      // 中文常用词的替换
      [/С/g, '小'], [/Ů/g, '女'], [/ӣ/g, '子'], [/ǰ/g, '前'], [/ĸ/g, '母'],
      [/ʱ/g, '时'], [/˵/g, '说'], [/һ/g, '一'], [/ô/g, '么'], [/ܵ/g, '能的'],
      [/Ҳ/g, '也'], [/ˣ/g, '了，'], [/ǵ/g, '的'], [/֪/g, '知'], [/ĵ/g, '的地'],
      [/Լ/g, '自己'], [/ֻ/g, '只'], [/ģ/g, '的模'], [/ϲ/g, '喜'], [/Ϊ/g, '为'],
      
      // 去除多余控制字符
      [/[\x00-\x09\x0B\x0C\x0E-\x1F]/g, ''],
      
      // 移除常见乱码符号
      [/\ufffd/g, ''], [/\u65533/g, ''], 
      
      // 尝试修复常见的乱码组合
      [/ĵ/g, '的'], [/Ĺ/g, '的关'], [/ļ/g, '的记'],
      [/ڵ/g, '在的'], [/ִ/g, '执'], [/׵/g, '父的'],
      [/ĸ/g, '母'], [/Ů/g, '女'], [/ѧ/g, '学'],
      [/С/g, '小'], [/ʱ/g, '时'], [/ҵ/g, '业的'],
      
      // 针对GBK特定替换 - 常见乱码对应的中文字符
      [/ï¼/g, '："'], // 引号替换
      [/â€œ/g, '"'], // 双引号左
      [/â€/g, '"'], // 双引号右
      [/â€˜/g, "'"], // 单引号左
      [/â€™/g, "'"], // 单引号右
      [/â€¦/g, '…'], // 省略号
      [/â€"/g, '—'], // 破折号
      
      // 中文标点符号替换
      [/ã€/g, '，'], // 逗号
      [/ã€‚/g, '。'], // 句号
      [/ï¼/g, '？'], // 问号
      [/ï¼/g, '！'], // 感叹号
      [/ï¼›/g, '；'], // 分号
      [/ï¼š/g, '：'], // 冒号
      [/ï¼ˆ/g, '（'], // 左括号
      [/ï¼‰/g, '）'], // 右括号
      
      // 其他特殊替换
      [/\?\?\?+/g, ''], // 连续问号
      [/\)\)\)+/g, ''], // 连续右括号
      [/\]\]\]+/g, ''], // 连续右方括号
      [/\}\}\}+/g, ''] // 连续右花括号
    ];
    
    // 应用所有替换
    chineseReplacements.forEach(([pattern, replacement]) => {
      fixedContent = fixedContent.replace(pattern, replacement);
    });
    
    // 处理严重乱码的情况 - 只保留有效字符
    fixedContent = fixedContent
      // 将连续多个无法识别的字符替换为单个空格
      .replace(/[^\u0000-\u007F\u4e00-\u9fa5\u3000-\u303F\uFF00-\uFFEF]+/g, ' ')
      // 移除连续空格
      .replace(/\s{2,}/g, ' ')
      // 处理多个连续空行
      .replace(/\n{3,}/g, '\n\n')
      // 去除每行开头空白
      .replace(/^\s+/gm, '')
      // 整体修剪
      .trim();
    
    // 如果处理后字符串很短，说明可能过滤过度，返回原字符串
    if (fixedContent.length < content.length * 0.1 && content.length > 1000) {
      console.warn('乱码处理过度，导致内容大幅减少，返回部分处理的内容');
      // 应用基本处理
      return content
        .replace(/\ufffd/g, '')
        .replace(/\n{3,}/g, '\n\n')
        .replace(/^\s+/gm, '')
        .trim();
    }
    
    return fixedContent;
  }
  
  // 默认UTF-8处理，只进行基本格式化
  return content
    .replace(/\n{3,}/g, '\n\n') // 多个连续空行替换为双空行 
    .replace(/^\s+/gm, '') // 去除每行开头空白
    .trim(); // 整体修剪
} 